/*
 * Functor.cpp
 *
 *  Created on: 20/nov/2010
 *      Author: computer
 */

#include "Functor.h"
#include "FlowExpression.h"
#include "TemplatePattern.cpp" //TODO warning
#include <sstream>

namespace TreeExpression {

Functor::Functor(const std::string& _nameFunctor) : FlowExpression(), nameFunctor(_nameFunctor) { }

Functor::Functor(const Functor& copy) : Expression(copy), FlowExpression(copy), listPattern(copy.listPattern), nameFunctor(copy.nameFunctor) { }

Functor::~Functor() { }

int Functor::match(const AutoPointer<Expression>& expr) {
	int ris = 1;
	std::list< Pattern<> >::iterator j;
	if (expr.isNull() && listPattern.empty()) return 1;//void function
	else if (expr.isNull()) return 0;//void function calling on function non void
	AutoPointer<Expression> param = expr;
	bool flag = true;
	for (j = listPattern.begin(); (j != listPattern.end()) && flag; ++j) {
		ris *= j->match(param);
		if (ris == 0) return ris;
		if (param->hasLeaf()) param = param->getLeaf();
		else flag = false;
	}
	//TODO reset pattern
	if (j != listPattern.end()) return 0; //different number of parameter
	if (flag) return 0;
	return ris;
}

//WARNING reverse insert for the stack
void Functor::addPattern(const Pattern<>& pattern) {
	listPattern.push_front(pattern);
}

std::list< Pattern<> > Functor::getPattern() const {
	return listPattern;
}

void Functor::setPattern(const std::list< Pattern<> >& _listPattern) {
	listPattern = _listPattern;
}

std::string Functor::getHash() const {
	return nameFunctor;
}

std::string Functor::toString() const {
	std::ostringstream oss;
	oss << nameFunctor << "( ";
	std::list< Pattern<> >::const_iterator i = listPattern.begin();
	while (i != listPattern.end()) {
		oss << i->toString();
		++i;
		if (i != listPattern.end()) oss << ", ";
	}
	oss << ")";
	return oss.str();
}

std::string Functor::getName() const {
	return nameFunctor;
}

bool Functor::equal(Functor* snd) const {
	if (nameFunctor != snd->nameFunctor) return false;
	if (listPattern.size() != snd->listPattern.size()) return false;
	std::list< Pattern<> >::const_iterator i = listPattern.begin();
	std::list< Pattern<> >::const_iterator j = snd->listPattern.begin();
	while (i != listPattern.end()) {
		if (i->getHash() != j->getHash()) return false;
		++i;
		++j;
	}
	return true;
}

}
